home *** CD-ROM | disk | FTP | other *** search
/ Mac Easy 2010 May / Mac Life Ubuntu.iso / casper / filesystem.squashfs / usr / share / ghostscript / 8.64 / Resource / Init / gs_ttf.ps < prev    next >
Encoding:
Text File  |  2009-04-17  |  76.7 KB  |  1,968 lines

  1. %    Copyright (C) 1996-2003 Artifex Software, Inc.  All rights reserved.
  2. % This software is provided AS-IS with no warranty, either express or
  3. % implied.
  4. % This software is distributed under license and may not be copied,
  5. % modified or distributed except as expressly authorized under the terms
  6. % of the license contained in the file LICENSE in this distribution.
  7. % For more information about licensing, please refer to
  8. % http://www.ghostscript.com/licensing/. For information on
  9. % commercial licensing, go to http://www.artifex.com/licensing/ or
  10. % contact Artifex Software, Inc., 101 Lucas Valley Road #110,
  11. % San Rafael, CA  94903, U.S.A., +1(415)492-9861.
  12.  
  13. % $Id: gs_ttf.ps 9296 2008-12-18 23:37:32Z alexcher $
  14. % Support code for direct use of TrueType fonts.
  15. % (Not needed for Type 42 fonts.)
  16.  
  17. % Note that if you want to use this file without including the ttfont.dev
  18. % option when you built Ghostscript, you will need to load the following
  19. % files before this one:
  20. %    lib/gs_mgl_e.ps
  21. %    lib/gs_mro_e.ps
  22. %    lib/gs_wan_e.ps
  23.  
  24. % Thanks to B. Jackowski and GUST (the Polish TeX Users' Group) for
  25. % the glyf-splitting code.
  26.  
  27. % ---------------- Font loading machinery ---------------- %
  28.  
  29. % Augment the FONTPATH machinery so it recognizes TrueType fonts.
  30.  
  31. /.scanfontheaders where {
  32.   pop /.scanfontheaders [
  33.    .scanfontheaders aload pop (\000\001\000\000*) (true*)
  34.   ] def
  35. } if
  36.  
  37. % <file> <key> .findfontvalue <value> true
  38. % <file> <key> .findfontvalue false
  39. % Closes the file in either case.
  40. /.findnonttfontvalue /.findfontvalue load def
  41. /.findfontvalue {
  42.   1 index read {
  43.     2 index 1 index unread
  44.     % beginning with binary 0 or 't' (TrueType), or 'O' (OpenType)
  45.     dup 0 eq 1 index (O) 0 get eq or exch (t) 0 get eq or {
  46.         % If this is a font at all, it's a TrueType font.
  47.       dup /FontType eq {
  48.         pop closefile 42 true
  49.       } {
  50.         dup /FontName eq { pop .findttfontname } { pop closefile false } ifelse
  51.       } ifelse
  52.     } {
  53.         % Not a TrueType font.
  54.       .findnonttfontvalue
  55.     } ifelse
  56.   } { pop closefile false } ifelse
  57. } bind def
  58.  
  59. % <file> .findttfontname <fname> true
  60. % <file> .findttfontname false
  61. % Closes the file in either case.
  62. /.findttfontname {
  63.   //true 0 .loadttfonttables
  64.   tabdict /name .knownget {
  65.     dup 8 getu32 f exch setfileposition
  66.     12 getu32 string f exch readstring pop
  67.     dup
  68.     6 findname not {
  69.       4 findname    % Try FullName
  70.     } {
  71.       exch pop true
  72.     }
  73.     ifelse
  74.   } {
  75.     false
  76.   } ifelse
  77.   f closefile end end
  78. } bind def
  79.  
  80. % Load a font file that might be a TrueType font.
  81.  
  82. /tt_tag_dict << <00010000> 0 (true) 0 (typ1) 0 (ttcf) 0 >> readonly def
  83.  
  84. % <file> .loadfontfile -
  85. /.loadnonttfontfile /.loadfontfile load def
  86. /.loadfontfile {
  87.   dup (1234) .peekstring { //tt_tag_dict exch known } { //false } ifelse {
  88.         % If this is a font at all, it's a TrueType font.
  89.     .loadttfont pop
  90.   } {
  91.         % Not a TrueType font.
  92.     .loadnonttfontfile
  93.   } ifelse
  94. } bind def
  95.  
  96. currentdict /tt_tag_dict .undef
  97.  
  98. % ---------------- Automatic Type 42 generation ---------------- %
  99.  
  100. % Load a TrueType font from a file as a Type 42 PostScript font.
  101. % The thing that makes this really messy is the handling of encodings.
  102. % There are 2 interacting tables that affect the encoding:
  103. %       'cmap' provides multiple maps from character codes to glyph indices
  104. %       'post' maps glyph indices to glyph names (if present)
  105. % What we need to get out of this is:
  106. %       Encoding mapping character codes to glyph names
  107. %         (the composition of cmap and post)
  108. %       CharStrings mapping glyph names to glyph indices
  109. %         (the inverse of post)
  110. % If the post table is missing, we have to take a guess based on the cmap
  111. % table.
  112.  
  113. /.loadttfontdict 50 dict dup begin
  114.  
  115. /orgXUID AladdinEnterprisesXUID def
  116. /maxstring 32764 def    % half the maximum length of a PostScript string,
  117.             % must be a multiple of 4 (for hmtx / loca / vmtx)
  118.  
  119. /.invert_encoding   % <array> invert_encoding <dict>
  120. { dup 256 dict exch
  121.   0 exch 1 exch length 1 sub {     % [] <> i
  122.     dup 3 index exch get           % [] <> i v
  123.     dup /.notdef ne {
  124.       exch 2 index 2 index .knownget {
  125.         dup type /arraytype eq {
  126.       [ exch aload pop counttomark 2 add -1 roll ]
  127.         } {
  128.       exch 2 array astore
  129.         } ifelse
  130.       } if 2 index 3 1 roll put
  131.     } {
  132.       pop pop
  133.     } ifelse
  134.   } for
  135.   exch pop
  136. } bind def
  137.  
  138. % Make /MacRomanEncodingForTrueType including additional
  139. % characters in Mac OS Roman encoding, which is missing
  140. % in /MacRomanEncoding. See PDF spec 1.7, p. 431 or
  141. % "Inside Macintosh: Text" 1-55, Figure 1-36.
  142. % This is useful to exploit the glyphs via Apple Roman
  143. % TrueType cmap subtable, but not appropriate for information
  144. % interchange.
  145.  
  146. /MacRomanEncodingForTrueType
  147.   /MacRomanEncoding .findencoding
  148.   dup length array copy
  149.   <<
  150.     /notequal    173
  151.     /infinity    176
  152.     /lessequal    178
  153.     /greaterequal    179
  154.     /partialdiff    182
  155.     /summation    183
  156.     /product    184
  157.     /pi        185
  158.     /integral    186
  159.     /Omega        189
  160.     /radical    195
  161.     /approxequal    197
  162.     /Delta        198
  163.     /lozenge    215
  164.     /Euro        219
  165.     /apple        240
  166.   >> {
  167.     TTFDEBUG { (Extend MacRomanEncodingForTrueType for TrueType: ) =only } if
  168.  
  169.     % check /.notdef to avoid overwriting
  170.     2 index 1 index get dup /.notdef eq {
  171.       TTFDEBUG { (insert /) =only 2 index =only ( @ ) =only 1 index == } if
  172.       pop
  173.       exch 2 index 3 1 roll put
  174.     } {
  175.       TTFDEBUG { (cannot insert /) =only 2 index =only ( @ ) =only 1 index =only ( used for ) =only dup == } if
  176.       pop
  177.       pop pop
  178.     } ifelse
  179.   } forall
  180.   aload pop
  181.   256 packedarray
  182.   5 1 index .registerencoding
  183. .defineencoding
  184.  
  185. % Define the Macintosh standard mapping from characters to glyph indices.
  186. /MacRomanEncoding dup .findencoding def
  187. /MacGlyphEncoding dup .findencoding def
  188. /MacRomanEncodingForTrueType dup .findencoding def
  189.  
  190. % Invert the MacRomanEncoding.
  191. /.romanmacdict MacRomanEncodingForTrueType .invert_encoding def
  192. /.latin1isodict ISOLatin1Encoding .invert_encoding def
  193.  
  194. % Define remapping for misnamed glyphs in TrueType 'post' tables.
  195. % There are probably a lot more than this!
  196. % Also see /postalias table below.
  197. /postremap mark
  198.   /Eoverdot /Edotaccent
  199.   /eoverdot /edotaccent
  200. .dicttomark readonly def
  201.  
  202. % Array used for fast pre-filling of cmap array
  203. /.array1024z [ 1024 { 0 } repeat ] def
  204.  
  205. % ---- Utilities ---- %
  206.  
  207. % Define a serial number for creating unique XUIDs for TrueType fonts.
  208. % We used to use the checkSumAdjustment value from the font, but this is
  209. % not reliable, since some fonts don't set it correctly.
  210. % Note that we must do this in a string to make it immune to save/restore.
  211. /xuidstring <80000000> def
  212. /curxuid {        % - curxuid <int>
  213.   0 xuidstring { exch 8 bitshift exch add } forall
  214. } bind def
  215. /nextxuid {        % - nextxuid -
  216.   3 -1 0 {
  217.     xuidstring 1 index 2 copy get dup 255 ne {
  218.       1 add put pop exit
  219.     } if pop 0 put pop
  220.   } for
  221. } bind def
  222.  
  223. % <string> <index> getu16 <integer>
  224. /getu16 {
  225.   2 copy get 8 bitshift 3 1 roll 1 add get add
  226. } bind def
  227.  
  228. % <string> <index> gets16 <integer>
  229. /gets16 {
  230.   getu16 16#8000 xor 16#8000 sub
  231. } bind def
  232.  
  233. % <string> <index> getu32 <integer>
  234. /getu32 {
  235.   2 copy getu16 16 bitshift 3 1 roll 2 add getu16 add
  236. } bind def
  237.  
  238. % <string> <index> gets32 <integer>
  239. /gets32 {
  240.   2 copy gets16 16 bitshift 3 1 roll 2 add getu16 add
  241. } bind def
  242.  
  243. % <string|array> <index> getu16 <integer>
  244. /getu16a {
  245.   2 getinterval_from_stringarray 0 getu16
  246. } bind def
  247.  
  248. % <string|array> <index> gets16 <integer>
  249. /gets16a {
  250.   2 getinterval_from_stringarray 0 gets16
  251. } bind def
  252.  
  253. % <string|array> <index> getu32a <integer>
  254. /getu32a {
  255.   4 getinterval_from_stringarray 0 getu32
  256. } bind def
  257.  
  258. % <string|array> <index> gets32a <integer>
  259. /gets32a {
  260.   4 getinterval_from_stringarray 0 gets32
  261. } bind def
  262.  
  263. 16#ffffffff 0 gt {  % 64-bit sign extension
  264.   { /curxuid /gets32 /gets32a} {
  265.     mark 1 index load aload pop { 16#80000000 xor 16#80000000 sub } aload pop
  266.     .packtomark cvx def
  267.   } bind forall
  268. } if
  269.  
  270. % <string> <index> <integer> putu16 -
  271. /putu16 {
  272.   3 copy -8 bitshift put
  273.   exch 1 add exch 16#ff and put
  274. } bind def
  275.  
  276. % <string> <index> <integer> putu32 -
  277. /putu32 {
  278.   3 copy -16 bitshift putu16
  279.   exch 2 add exch 16#ffff and putu16
  280. } bind def
  281.  
  282. % <nametable> <nameid> findname <string> true
  283. % <nametable> <nameid> findname false
  284. /findname {
  285.   TTFDEBUG { (findname: ) print dup =only  } if
  286.   false 3 1 roll
  287.   1 index length 0 gt {    % check for zero length name table 
  288.     0 1 3 index 2 getu16 1 sub {
  289.         % Stack: false table id index
  290.       12 mul 6 add 2 index exch 12 getinterval
  291.       dup 6 getu16 2 index eq {
  292.           % We found the name we want.
  293.     exch pop
  294.           % Stack: false table record
  295.     dup 10 getu16 2 index 4 getu16 add
  296.     1 index 8 getu16 4 -1 roll 3 1 roll
  297.         3 copy add 1 index length
  298.         le {
  299.           pop
  300.           getinterval exch
  301.           % Stack: false string record
  302.           % Check for 8- vs. 16-bit characters.
  303.       is2byte { true } { dup is2byte2 } ifelse { string2to1 } if true null 4 -1 roll exit
  304.         } {
  305.           pop pop pop pop
  306.           false
  307.           exit
  308.         } ifelse
  309.       } if pop
  310.     } for
  311.   } if
  312.   pop pop
  313.   TTFDEBUG {
  314.     dup { ( = ) print 1 index == } { ( not found) = } ifelse
  315.   } if
  316. } bind def
  317.  
  318. % <namerecord> is2byte <bool>
  319. /is2byte {
  320.   dup 0 getu16 {
  321.     { pop true }        % Apple Unicode
  322.     { pop false }        % Macintosh Script manager
  323.     { 1 getu16 1 eq }        % ISO
  324.     { 1 getu16 1 eq }        % Microsoft
  325.   } exch get exec
  326. } bind def
  327.  
  328. % <string> is2byte2 <bool>
  329. /is2byte2 {
  330.   dup length 
  331.   dup 2 mod 0 ne {
  332.     pop pop false
  333.   } {            % s l
  334.     true exch   % s b l
  335.     1 sub 0 exch 2 exch {
  336.       2 index exch get 0 ne {
  337.         pop false exit
  338.       } if
  339.     } for
  340.     exch pop
  341.   } ifelse
  342. } bind def
  343.  
  344. % <string2> string2to1 <string>
  345. /string2to1 {
  346.   dup length 2 idiv string dup
  347.   0 1 3 index length 1 sub {
  348.     3 index 1 index 2 mul 1 add get put dup
  349.   } for pop exch pop
  350. } bind def
  351.  
  352. % Each procedure in this dictionary is called as follows:
  353. %       <encodingtable> proc <glypharray>
  354. /cmapformats mark
  355.   0 {        % Apple standard 1-to-1 mapping.
  356.     6 256 getinterval_from_stringarray
  357.     mark 0 3 -1 roll
  358.     { 1 index 1 add } forall pop
  359.     .dicttomark
  360.   } bind
  361.   2 {        % Apple 16bit CJK (ShiftJIS etc)
  362.  
  363.     % /sHK_sz        subHeaderKey_size    % 1 * uint16
  364.     % /sH_sz        subHeader_size        % 4 * uint16
  365.     % /sH_len        subHeader_length
  366.     % /cmapf2_tblen    total table length
  367.     % /cmapf2_lang    language code (not used)
  368.     % /sHKs        subHeaderKeys
  369.  
  370.     /sHK_sz 2 def
  371.     /sH_sz 8 def
  372.     dup 2 getu16a /cmapf2_tblen exch def
  373.  
  374.     dup 4 getu16a /cmapf2_lang exch def
  375.  
  376.     dup 6 256 sHK_sz mul getinterval_from_stringarray /sHKs exch def
  377.  
  378.     0        % initialization value for /sH_len
  379.     0 1 255 {
  380.        sHKs exch
  381.        2 mul getu16a
  382.        1 index    % get current max
  383.        1 index    % get current subHeaderKey
  384.        lt {exch} if pop
  385.     } for
  386.     /sH_len exch def
  387.  
  388.     dup 6 256 sHK_sz mul add
  389.     cmapf2_tblen 1 index sub getinterval_from_stringarray
  390.     /sH_gIA exch def
  391.  
  392.     /cmapf2_glyph_array 0 dict def
  393.  
  394.     /.cmapf2_putGID {
  395.         /cmapf2_ch cmapf2_ch_hi 8 bitshift cmapf2_ch_lo add def
  396.         firstCode cmapf2_ch_lo le
  397.         cmapf2_ch_lo firstCode entryCount add lt
  398.         and { % true: j is inside
  399.             sH_offset idRangeOffset add        % offset to gI
  400.             cmapf2_ch_lo firstCode sub 2 mul    % rel. pos. in range
  401.             add 6 add                % offset in sH_gIA
  402.             sH_gIA exch getu16a
  403.             dup 0 gt { %
  404.                 idDelta add
  405.                 cmapf2_glyph_array exch cmapf2_ch exch put
  406.             } {
  407.                 pop
  408.                 % cmapf2_glyph_array cmapf2_ch 0 put
  409.             } ifelse
  410.         } {   % false: j is outside
  411.             % cmapf2_glyph_array cmapf2_ch 0 put
  412.         } ifelse
  413.     } def
  414.  
  415.     16#00 1 16#ff { % hi_byte scan
  416.         /cmapf2_ch_hi exch def
  417.         sHKs cmapf2_ch_hi sHK_sz mul getu16a
  418.         /sH_offset exch def
  419.         sH_gIA sH_offset sH_sz getinterval
  420.             dup 0 getu16a /firstCode exch def
  421.             dup 2 getu16a /entryCount exch def
  422.             dup 4 gets16a /idDelta exch def
  423.             dup 6 getu16a /idRangeOffset exch def
  424.         pop
  425.         sH_offset 0 eq {
  426.            /cmapf2_ch_lo cmapf2_ch_hi def
  427.            /cmapf2_ch_hi 0 def
  428.            .cmapf2_putGID
  429.         } {
  430.            16#00 1 16#ff { % lo_byte scan
  431.                /cmapf2_ch_lo exch def
  432.                .cmapf2_putGID
  433.            } for
  434.         } ifelse
  435.      } for
  436.      pop
  437.      cmapf2_glyph_array
  438.   } bind
  439.   4 {        % Microsoft/Adobe segmented mapping.
  440.     /etab exch def
  441.     /nseg2 etab 6 getu16a def
  442.     14 /endc etab 2 index nseg2 getinterval_from_stringarray def
  443.         % The Apple TrueType documentation omits the 2-byte
  444.         % 'reserved pad' that follows the endCount vector!
  445.     2 add
  446.     nseg2 add /startc etab 2 index nseg2 getinterval_from_stringarray def
  447.     nseg2 add /iddelta etab 2 index nseg2 getinterval_from_stringarray def
  448.     nseg2 add /idroff etab 2 index nseg2 getinterval_from_stringarray def
  449.         % The following hack allows us to properly handle
  450.         % idiosyncratic fonts that start at 0xf000:
  451.     pop
  452.     /firstcode startc 0 getu16a 16#ff00 and dup 16#f000 ne { pop 0 } if def
  453.     /putglyph {
  454.       glyphs code 3 -1 roll put /code code 1 add def
  455.     } bind def
  456.         % Do a first pass to compute the size of the glyphs array.
  457.     /numcodes 0 def
  458.     /glyphs 0 dict def
  459.     0 0 2 nseg2 3 sub {
  460.         % Stack: /glyphs numglyphs i2
  461.       /i2 exch def
  462.       /scode startc i2 getu16a def
  463.       /ecode endc i2 getu16a def
  464.       numcodes scode firstcode sub
  465.         % Hack for fonts that have only 0x0000 and 0xf000 ranges
  466.       %dup 16#e000 ge { 255 and } if
  467.       % the previous line is obstructive to CJK fonts, so it was removed
  468.       exch sub 0 .max ecode scode sub 1 add add
  469.       exch 1 index add exch
  470.       numcodes add /numcodes exch def
  471.     } for pop
  472.  
  473.         % Now fill in the array.
  474.     /numcodes 0 def /code 0 def
  475.     0 2 nseg2 3 sub {
  476.       /i2 exch def
  477.       /scode startc i2 getu16a def
  478.       /ecode endc i2 getu16a def
  479.       numcodes scode firstcode sub
  480.         % Hack for fonts that have only 0x0000 and 0xf000 ranges
  481.       %dup 16#e000 ge { 255 and } if
  482.       % the previous line is obstructive to CJK fonts, so it was removed
  483.       exch sub 0 .max dup /code exch code exch add def
  484.       ecode scode sub 1 add add numcodes add /numcodes exch def
  485.       /delta iddelta i2 gets16a def
  486.       TTFDEBUG {
  487.     (scode=) print scode =only
  488.     ( ecode=) print ecode =only
  489.     ( delta=) print delta =only
  490.     ( droff=) print idroff i2 getu16 =
  491.       } if
  492.       idroff i2 getu16a dup 0 eq {
  493.     pop scode delta add 65535 and 1 ecode delta add 65535 and
  494.     { putglyph } for
  495.       } {    % The +2 is for the 'reserved pad'.
  496.         /gloff exch 14 nseg2 3 mul add 2 add i2 add add def
  497.         0 1 ecode scode sub {
  498.       2 mul gloff add etab exch getu16a
  499.       dup 0 ne { delta add 65535 and } if putglyph
  500.     } for
  501.       } ifelse
  502.     } for glyphs /glyphs null def    % for GC
  503.   } bind
  504.   6 {        % Single interval lookup.
  505.     dup 6 getu16a /firstcode exch def
  506.     dup 8 getu16a /ng exch def
  507.     firstcode ng add dict
  508.         % Stack: tab array
  509.         % Fill elements 0 .. firstcode-1 with 0
  510.     0 1 firstcode 1 sub { 2 copy 0 put pop } for
  511.     dup 
  512.         % Stack: tab dict dict
  513.         % Fill elements firstcode .. firstcode+nvalue-1 with glyph values
  514.     0 1 ng 1 sub {
  515.       dup firstcode add exch
  516.       2 mul 10 add 4 index exch getu16a 3 copy put pop pop
  517.     } for pop exch pop
  518.   } bind
  519. .dicttomark readonly def                % cmapformats
  520.  
  521. % <cmaptab> cmaparray <glypharray>
  522. /cmaparray {
  523.   dup 0 getu16a cmapformats exch .knownget {
  524.     TTFDEBUG {
  525.       (cmap: format ) print 1 index 0 getu16a = flush
  526.     } if exec
  527.   } {
  528.     (Can't handle format ) print 0 getu16a = flush
  529.     mark 0 1 255 { dup } for .dicttomark
  530.   } ifelse
  531.   TTFDEBUG {
  532.     (cmap: length=) print dup length = dup ===
  533.   } if
  534. } bind def
  535.  
  536. /get_from_stringarray % <array|string> <offset> get_from_stringarray <int>
  537. { 1 index type /stringtype eq {
  538.     get
  539.   } {
  540.     exch {                % o ()
  541.       2 copy length ge {
  542.         length sub
  543.       } {
  544.         exch get exit
  545.       } ifelse
  546.     } forall
  547.   } ifelse
  548. } bind def
  549.  
  550. /getinterval_from_stringarray % <array|string> <offset> <length> getinterval_from_stringarray <string>
  551. { % May allocate a string in VM.
  552.   2 index type /stringtype eq {
  553.     getinterval
  554.   } {
  555.     dup 65535 le { 
  556.       string exch 0                                 % [] s o p
  557.       4 3 roll {                                    % s o p Si
  558.         dup length                                  % s o p Si lSi
  559.         dup 4 index lt {
  560.           3 index exch sub                          % s o p Si o'
  561.           exch pop 3 1 roll exch pop                % s o' p
  562.         } {                                         % s o p Si lSi
  563.           dup 3 1 roll                              % s o p lSi Si lSi
  564.           4 index sub                               % s o p lSi Si lSi-o
  565.           5 index length 4 index sub                % s o p lSi Si lSi-o ls-p
  566.           2 copy gt { exch } if pop                 % s o p lSi Si minl
  567.           dup 3 1 roll                              % s o p lSi minl Si minl
  568.           5 index exch getinterval                  % s o p lSi minl from
  569.           5 index 4 index 3 index                   % s o p lSi minl from s p minl
  570.           getinterval                               % s o p lSi minl from to
  571.           copy pop                                  % s o p lSi minl
  572.           exch pop add exch pop 0 exch              % s 0 p'
  573.           dup 3 index length ge { exit } if
  574.         } ifelse
  575.       } forall
  576.       pop pop                                       % s
  577.     } {
  578.       [ 4 1 roll
  579.         {
  580.           dup 0 eq {
  581.             pop pop pop exit
  582.           } if 
  583.           3 copy 
  584.           dup 65535 ge {
  585.             pop 65535
  586.           } if
  587.           getinterval_from_stringarray 4 1 roll
  588.           3 index length sub
  589.           exch
  590.           3 index length add
  591.           exch
  592.         } loop
  593.       ]
  594.     } ifelse
  595.   } ifelse
  596. } bind def
  597.  
  598. /string_array_size  % <array|string> string_array_size <int>
  599. { dup type /stringtype eq {
  600.     length
  601.   } { 
  602.     0 exch { length add } forall
  603.   } ifelse
  604. } bind def
  605.  
  606. % Each procedure in this dictionary is called as follows:
  607. %       posttable <<proc>> glyphencoding
  608. /postformats mark
  609.   16#00010000  {    % 258 standard Macintosh glyphs.
  610.     pop MacGlyphEncoding
  611.   }
  612.   16#00020000  {    % Detailed map, required by Microsoft fonts.
  613.     dup dup type /arraytype  eq { 0 get } if length 36 lt {
  614.       TTFDEBUG { (post format 2.0 invalid.) = flush } if
  615.       pop [ ]
  616.     } {
  617.       /postglyphs exch def
  618.       /post_first postglyphs dup type /arraytype eq { 0 get } if def
  619.       post_first 32 getu16 /numglyphs exch def
  620.       /glyphnames numglyphs 2 mul 34 add def
  621.       % Build names array in the order they occur in the 'post' table
  622.       /postpos glyphnames def
  623.       /total_length postglyphs //string_array_size exec def
  624.       numglyphs array 0 1 numglyphs 1 sub {
  625.     postpos total_length ge {
  626.           % Fill the rest with .notdef
  627.           1 numglyphs 1 sub { 1 index exch /.notdef put } for
  628.           exit
  629.         } if
  630.     % No name available, /postnames will be defined as an empty
  631.     % array and the glyph won't get a name attached.
  632.     postglyphs postpos //get_from_stringarray exec
  633.         postglyphs postpos 1 add 2 index //getinterval_from_stringarray exec cvn
  634.     exch postpos add 1 add /postpos exch def
  635.         2 index 3 1 roll
  636.         put
  637.       } for
  638.       /postnames exch def
  639.  
  640.         % Some TrueType fonts converted by "Windows Type 1 Installer" have
  641.         % problematic post table including MacGlyphEncoding entries which
  642.         % should be omitted. Such extra entries in the beginning of glyphName
  643.         % array make /Encoding broken. If we find populary predefined
  644.         % ISOLatin1Encoding glyph name in the post table, empty encoding is
  645.         % returned. Some TrueType fonts for Microsoft Windows redefines
  646.         % MacGlyphEncoding glyph name out of predefined range). To permit
  647.         % such fonts, ISOLatin1Encoding is used to find broken post. Bug 689495.
  648.       /.broken_post //false def
  649.       tabdict /name .knownget {
  650.         (Windows Type 1 Installer V1.0) search {
  651.           pop pop pop
  652.           .latin1isodict postnames {
  653.             dup /.notdef ne {
  654.               2 copy known {
  655.                 TTFDEBUG { (ignore post table that redefines ISOLatin1Encoding glyph name ) print dup == flush } if
  656.                 /.broken_post //true def
  657.                 pop exit
  658.               } if
  659.             } if
  660.             pop
  661.           } forall
  662.           pop
  663.         } {
  664.           pop
  665.         } ifelse
  666.       } if
  667.  
  668.       numglyphs array 0 1 numglyphs 1 sub {
  669.     dup 2 mul 34 add postglyphs exch 2 //getinterval_from_stringarray exec 
  670.     dup 0 get 8 bitshift exch 1 get add dup 258 lt {
  671.       MacGlyphEncoding exch get
  672.     } {
  673.       dup 32768 ge {
  674.         % According to the published TrueType spec, such values are
  675.         % "reserved for future use", but at least some PDF files
  676.         % produced by the Adobe PDF library contain entries with a
  677.         % value of 16#ffff.
  678.         pop /.notdef
  679.       } {
  680.         % Get the name for this glyph
  681.         258 sub dup postnames length ge {
  682.           TTFDEBUG { (   *** warning: glyph index past end of 'post' table) = flush } if
  683.           pop
  684.           exit
  685.         } if
  686.         postnames exch get
  687.         % At least some of Microsoft's TrueType fonts use incorrect
  688.         % (Adobe-incompatible) names for some glyphs.
  689.         % Correct for this here.
  690.         postremap 1 index .knownget { exch pop } if
  691.       } ifelse
  692.     } ifelse
  693.     2 index 3 1 roll put
  694.       } for
  695.  
  696.       .broken_post {
  697.         pop
  698.         [ postnames aload length 1 roll ]
  699.       } if
  700.     }
  701.     ifelse
  702.   } bind
  703.   16#00030000  {    % No map.
  704.     pop [ ]
  705.   } bind
  706. .dicttomark readonly def                % postformats
  707.  
  708. /call.readtable
  709. { .readtable
  710. } bind def
  711. /call.readbigtable
  712. { .readbigtable
  713. } bind def
  714.  
  715. % Each procedure in this dictionary is called as follows:
  716. %    <file> <length> -proc- <string|array_of_strings>
  717. % Note that each table must have an even length, because of a strange
  718. % Adobe requirement that each sfnts entry have even length.
  719. /readtables mark
  720.     % Ordinary tables
  721.   (head) //call.readtable
  722.   (hhea) 1 index
  723.   (maxp) 1 index
  724.   (name) 1 index
  725.   (OS/2) 1 index
  726.   (post) //call.readbigtable
  727.   (vhea) //call.readtable
  728.     % Big tables
  729.   (cmap) //call.readbigtable
  730.   (GSUB) //call.readbigtable
  731.   (glyf) //call.readbigtable
  732.   (loca) 1 index
  733.   (hmtx) 1 index
  734.   (vmtx) 1 index
  735.     % Tables only needed for embedding in PDF files
  736.   (cvt ) //call.readtable
  737.   (fpgm) 1 index
  738.   (prep) 1 index
  739. .dicttomark
  740. % Normally there would be a 'readonly' here, but the ttf2pf utility wants
  741. % to include the 'kern' table as well, so we leave the readtables dictionary
  742. % writable.
  743. def                % readtables
  744.  
  745. /readtables_stripped readtables dup length dict copy
  746. dup (loca) { .skiptable } put
  747. dup (glyf) { .skiptable } put
  748. def
  749.  
  750. % Read a table as a single string.
  751. % <file> <length> .skiptable <string>
  752. /.skiptable {
  753.   pop pop ()
  754. } bind def
  755.  
  756. % Read a table as a single string.
  757. % <file> <length> .readtable <string>
  758. /.readtable {
  759.   dup dup 1 and add string
  760.         % Stack: f len str
  761.   dup 0 4 -1 roll getinterval
  762.         % Stack: f str str1
  763.     % Because of the absurd PostScript specification that gives an
  764.     % error for reading into an empty string, we have to check for
  765.     % this explicitly here.
  766.   3 -1 roll exch
  767.   dup () ne { readstring } if pop pop
  768. } bind def
  769.  
  770. % Read a big table (one that may exceed 64K).
  771. % <file> <length> .readbigtable <string[s]>
  772. /.readbigtable {
  773.   dup 65400 lt {
  774.     .readtable
  775.   } {
  776.     currentuserparams /VMReclaim get -2 vmreclaim
  777.     [ 4 2 roll {
  778.         % Stack: mark ... f left
  779.       dup maxstring le { exit } if
  780.       1 index maxstring string readstring pop 3 1 roll maxstring sub
  781.     } loop .readtable ]
  782.     exch vmreclaim
  783.   } ifelse
  784. } bind def
  785.  
  786. end readonly def                % .loadttfontdict
  787.  
  788. % <tab> .printtab -
  789. /.printtab {
  790.   dup 0 4 getinterval print ( ) print
  791.   dup 8 getu32 =only ( ) print
  792.   12 getu32 =
  793. } bind def
  794.  
  795. % <file> <bool> <SubfontID> .loadttfonttables -
  796. % Pushes .loadttfontdict & scratch dict on d-stack.
  797. % Defines f, offsets, tables, tabdict, tabs.
  798. % Skips loca and glyf if <bool> is true.
  799. /.loadttfonttables {
  800.   .loadttfontdict begin
  801.   40 dict begin
  802.   /SubfontID exch def
  803.   /load_stripped exch def
  804.   /f exch def
  805.   /offsets f 12 string readstring pop def
  806.   load_stripped { readtables_stripped } { readtables } ifelse /readtables_ exch def
  807.   offsets 0 4 getinterval (ttcf) eq {
  808.     % We need to handle TT collections with disk fonts only.
  809.     % Therefore the file is a disk file and it can be positioned.
  810.     offsets 8 getu32 /num_fonts exch def
  811.     SubfontID num_fonts ge {
  812.       QUIET not { (True Type collection contains insufficient fonts.) = } if
  813.       /.loadttfonttables cvx /invalidfont signalerror
  814.     } if
  815.     SubfontID 4 mul 12 add f exch setfileposition
  816.     f 4 string readstring pop 0
  817.     getu32 /ttc_offset exch def
  818.     f ttc_offset setfileposition
  819.     /offsets f 12 string readstring pop def
  820.   } {
  821.     SubfontID 0 gt {
  822.       QUIET not { (SubfontID > 0 with a True Type file which is not a collection.) = } if
  823.       /.loadttfonttables cvx /invalidfont signalerror
  824.     } if
  825.     /ttc_offset 0 def
  826.   } ifelse
  827.   /tables f offsets 4 getu16 16 mul string readstring pop def
  828.   /tabdict tables length 16 idiv dict def
  829.     % tabs = tables we want to keep, sorted by file position.
  830.   /tabs [ 0 16 tables length 1 sub {
  831.     tables exch 16 getinterval
  832.     TTFDEBUG { dup .printtab } if
  833.     dup 0 4 getinterval readtables_ 1 index known {
  834.       % put all 0 length tables at 0 to avoid overlap
  835.       1 index 12 getu32 0 eq { 1 index 8 0 putu32 } if
  836.       tabdict exch 2 index put
  837.     } {
  838.       pop pop
  839.     } ifelse
  840.   } for ] {
  841.     exch 8 getu32 exch 8 getu32 lt
  842.   } .sort def
  843.     % In certain malformed TrueType fonts, tables overlap.
  844.     % Truncate tables if necessary.
  845.   0 1 tabs length 2 sub {
  846.     dup tabs exch get exch 1 add tabs exch get
  847.     1 index 8 getu32 2 index 12 getu32 add
  848.     1 index 8 getu32 gt {
  849.       (**** Warning: ) print 1 index 0 4 getinterval print
  850.       ( overlaps ) print dup 0 4 getinterval print
  851.       (, truncating.) = flush
  852.       dup 8 getu32 2 index 8 getu32 sub
  853.       2 index 12 3 -1 roll putu32
  854.     } if pop pop
  855.   } for
  856. } bind def
  857.  
  858. /.file_table_pos_names
  859. mark
  860. /glyf 0
  861. /loca 0
  862. .dicttomark readonly def
  863.  
  864. % - .readttdata -
  865. % Read data.  Updates offsets, tabs; stores data in tabdict.
  866. /.readttdata {
  867.   /file_table_pos 10 dict def
  868.   /fpos offsets length tables length add ttc_offset add def
  869.   /sfpos offsets length tabs length 16 mul add def
  870.   offsets 4 tabs length putu16
  871.   tabs {
  872.     dup 0 4 getinterval /tname exch def
  873.     dup 8 getu32 /tpos exch def
  874.     dup 12 getu32 /tlen exch def
  875.     load_stripped //.file_table_pos_names tname known and {
  876.         pop
  877.         file_table_pos tname [tpos tlen] put
  878.         tabdict tname () put
  879.     } {
  880.       8 sfpos putu32
  881.       % Skip data between the end of the previous table and
  882.     % the beginning of this one, if any.
  883.       tpos fpos gt {
  884.         load_stripped {
  885.           % 'setfileposition' is faster for skipping a big data.
  886.           f tpos setfileposition
  887.         } {
  888.           f tpos fpos sub () /SubFileDecode filter dup flushfile closefile
  889.           /fpos tpos def
  890.         } ifelse
  891.       } if
  892.       f tlen readtables_ tname get exec
  893.       tabdict tname 3 -1 roll put
  894.     % Round up the table length to an even value.
  895.       /sfpos sfpos tlen dup 1 and add add def
  896.     } ifelse
  897.     /fpos fpos tlen add def
  898.   } forall
  899. } bind def
  900.  
  901. % Find the string in a list of strings that includes a given index.
  902. % <strings> <index> .findseg <string> <index'>
  903. /.findseg {
  904.   exch {
  905.     dup length 2 index gt { exch exit } if
  906.     length sub
  907.   } forall
  908. } bind def
  909.  
  910. % - .makesfnts -
  911. % Defines checksum, getloca, head, locatable, numloca, post, sfnts, upem
  912. % Note that the 'loca' table may be out of order. This is handled when
  913. % needed in .dividesfnts
  914. /.makesfnts {
  915.   .readttdata
  916.   /head tabdict /head get def
  917.   /post tabdict /post .knownget { 
  918.     dup 0 get /post_first_part exch def 
  919.   } { 
  920.     null 
  921.   } ifelse def
  922.   load_stripped not {
  923.     /locatable tabdict /loca get def
  924.     /numloca
  925.       locatable dup type /stringtype eq
  926.        { length }
  927.        { 0 exch { length add } forall }
  928.       ifelse    % no def yet
  929.     locatable type /stringtype eq {
  930.       /.indexloca {} def
  931.     } {
  932.       /.indexloca /.findseg load def
  933.     } ifelse
  934.     head 50 getu16 0 ne {
  935.       /getloca {
  936.         2 bitshift locatable exch .indexloca getu32
  937.       } def
  938.       4 idiv 1 sub
  939.     } {
  940.       /getloca {
  941.         dup add locatable exch .indexloca getu16 dup add
  942.       } def
  943.       2 idiv 1 sub
  944.     } ifelse def        % numloca
  945.     % If necessary, re-partition the glyfs.
  946.     tabdict /glyf get dup type /stringtype ne {
  947.       .dividesfnts tabdict /glyf 3 -1 roll put
  948.     } {
  949.       pop
  950.     } ifelse
  951.   } {
  952.     % We did not load loca, take the number of glyphs from maxp.
  953.     /numloca tabdict /maxp get 4 getu16 def
  954.   } ifelse
  955.   /sfnts [
  956.     offsets tabs { concatstrings } forall
  957.     tabs {
  958.       0 4 getinterval tabdict exch get
  959.       dup type /stringtype ne { aload pop } if
  960.     } forall
  961.   ] def
  962. } bind def
  963.  
  964. % <glyfs> .dividesfnts <glyfs'>
  965. /.dividesfnts {
  966.   /glyfs exch def
  967.   /len1 0 glyfs { length add } forall def
  968.     % Determine where to split the glyfs by scanning the sorted locatable
  969.     % The very last entry in loca may be bogus.
  970.     % Note that some loca entries may be odd, but we can only
  971.     % split at even positions.
  972.     %
  973.     % Construct splitarray, the array of final lengths of
  974.     % the sfnts entries covering the glyfs (i.e., all but
  975.     % the first and last sfnts entries).
  976.     /prevsplit 0 def
  977.     /prevboundary 0 def
  978.     % sort the locatable in case it is out of order
  979.     % Note the 'loca' table remains unchanged
  980.     /needsort false def
  981.     numloca array    % the array of 'loca' entries (may be out of order)
  982.     -1    % initial values for in order check
  983.     0 1 numloca 1 sub {
  984.       dup getloca dup
  985.       4 -1 roll lt { /needsort true def } if 
  986.       3 copy put exch pop
  987.     } for pop        % discard inorder check value
  988.     needsort {
  989.       { lt } bind .sort     % stack: locatable_array
  990.     } if
  991.     /splitarray [
  992.       3 -1 roll 0 1 numloca 1 sub {
  993.     % stack: /splitarray -mark- { splitlen splitlen ... } locatable_array index
  994.     1 index exch get dup prevsplit maxstring add gt {
  995.       prevboundary prevsplit sub exch
  996.       /prevsplit prevboundary def
  997.     } if
  998.     dup 1 and 0 eq { /prevboundary exch def } { pop } ifelse
  999.     dup type /arraytype ne { exch } if    % keep locatable_array on top
  1000.       } for
  1001.       len1 prevsplit sub
  1002.       exch pop        % discard locatable_array
  1003.     ] def
  1004.     currentuserparams /VMReclaim get -2 vmreclaim
  1005.     [
  1006.     % Re-split the sfnts glyfs strings according to splitarray.
  1007.     % We do this by iterating over the final segments defined
  1008.     % by splitarray, and constructing them from pieces of the
  1009.     % current glyfs strings.  We recycle the current strings
  1010.     % when possible, to avoid stressing the allocator.
  1011.       /sfnt_idx 0 def
  1012.       /strpos 0 def
  1013.       /avail () def
  1014.       splitarray {
  1015.     /seglen exch def
  1016.     /segpos 0 def
  1017.     avail length seglen ge
  1018.       { avail 0 seglen getinterval /avail () def } { seglen string }
  1019.     ifelse
  1020.     {
  1021.       /str glyfs sfnt_idx get def
  1022.       /strlen str length def
  1023.       /strleft strlen strpos sub def
  1024.       seglen segpos sub strleft lt { exit } if
  1025.         % Copy the (rest of the) string into the new segment.
  1026.         % We know strleft <= segleft.
  1027.       dup segpos str strpos strleft getinterval putinterval
  1028.       /segpos segpos strleft add def
  1029.       /avail str def
  1030.       /sfnt_idx sfnt_idx 1 add def
  1031.       /strpos 0 def
  1032.       segpos seglen eq { exit } if
  1033.     } loop
  1034.         % Fill up the segment with an initial piece of the next
  1035.         % existing glyfs string.  We know strleft > segleft.
  1036.     /segleft seglen segpos sub def
  1037.     dup segpos str strpos segleft getinterval putinterval
  1038.     /strpos strpos segleft add def
  1039.       } forall
  1040.     ]
  1041.     exch vmreclaim
  1042. } bind def
  1043.  
  1044. /first_post_string % - first_post_string <string>
  1045. {
  1046.   post dup type /arraytype eq { 0 get } if
  1047. } bind def
  1048.  
  1049. % - .getpost -
  1050. % Uses post, defines glyphencoding
  1051. /.getpost {
  1052.   /glyphencoding post null eq {
  1053.     TTFDEBUG { (post missing) = flush } if [ ]
  1054.   } {
  1055.     postformats first_post_string 0 getu32 .knownget {
  1056.       TTFDEBUG {
  1057.     (post: format ) print
  1058.     first_post_string
  1059.     dup 0 getu16 =only (,) print 2 getu16 = flush
  1060.       } if
  1061.       post exch exec
  1062.     } {
  1063.       TTFDEBUG { (post: unknown format ) print post 0 getu32 = flush } if [ ]
  1064.     } ifelse
  1065.   } ifelse
  1066.   TTFDEBUG { (post=) print dup == } if
  1067.   def
  1068. } bind def
  1069.  
  1070. % - .ttkeys <key> <value> ...
  1071. /.ttkeys {
  1072.   count /ttkeycount exch def
  1073.   /upem head 18 getu16 def
  1074.   /FontMatrix matrix
  1075.   /FontBBox [ 36 2 42 { head exch gets16 upem div } for ]
  1076.   nextxuid
  1077.   tabdict /name .knownget {
  1078.         % Find the names from the 'name' table.
  1079.     /names exch def
  1080.     /FontName names 6 findname not { names 4 findname not { curxuid 16#ffffffff and 16 32 string cvrs } if } if
  1081.       /fontname 1 index def
  1082.     /FontInfo mark
  1083.       names 0 findname { /Notice exch } if
  1084.       names 1 findname { /FamilyName exch } if
  1085.       names 4 findname { /FullName exch } if
  1086.       names 5 findname { /Version exch } if
  1087.   } {
  1088.         % No name table, fabricate a FontName.
  1089.     /FontName curxuid 16#ffffffff and 16 32 string cvrs
  1090.       /fontname 1 index def
  1091.     /FontInfo mark
  1092.   } ifelse
  1093.         % Stack: ... /FontInfo mark key1 value1 ...
  1094.   post null ne {
  1095.     /ItalicAngle first_post_string 4 gets32 65536.0 div
  1096.     /isFixedPitch first_post_string 12 getu32 0 ne
  1097.     /UnderlinePosition first_post_string 8 gets16 upem div
  1098.     /UnderlineThickness first_post_string 10 gets16 upem div
  1099.   } if
  1100.   counttomark 0 ne { .dicttomark } { pop pop } ifelse
  1101.   /XUID [orgXUID 42 curxuid]
  1102.   TTFDEBUG {
  1103.     tabs { .printtab } forall
  1104.     [ sfnts { length } forall ] ==
  1105.     count ttkeycount sub array astore dup { == } forall aload pop
  1106.   } if
  1107.   /sfnts sfnts
  1108. } bind def
  1109.  
  1110. % ---------------- Standard TrueType font loading ---------------- %
  1111.  
  1112. % - .pickcmap_with_no_xlatmap -
  1113. % Defines cmapsub, cmaptab
  1114. /.pickcmap_with_no_xlatmap {
  1115.   tabdict /cmap get
  1116.         % The Apple cmap format is no help in determining the encoding.
  1117.         % Look for a Microsoft table.  If we can't find one,
  1118.         % just use the first table, whatever it is.
  1119.   dup 4 8 getinterval_from_stringarray exch  % () [] % the default
  1120.   0 1 2 index 2 getu16a 1 sub {              % () [] i
  1121.     8 mul 4 add 1 index exch 8 getinterval_from_stringarray % () [] ()
  1122.     TTFDEBUG {
  1123.       (cmap: platform ) print dup 0 getu16 =only
  1124.       ( encoding ) print dup 2 getu16 = flush
  1125.     } if
  1126.     dup 0 getu16 3 eq { exch 3 -1 roll pop exit } if pop
  1127.   } for
  1128.         % Stack: subentry table
  1129.   /cmapsub 2 index def  % () []
  1130.   exch 4 getu32 1 index string_array_size 1 index sub getinterval_from_stringarray
  1131.   /cmaptab exch def
  1132. } bind def
  1133.  
  1134. % - .pickcmap_with_xlatmap -
  1135. % Defines cmapsub, cmaptab
  1136. /.pickcmap_with_xlatmap {
  1137.   .xlatmap_dict /TrueType known not {
  1138.     (Emulating a CID font with a True Type file, ) print
  1139.     (the file gs/lib/xlatmap must contain /TrueType key.) =
  1140.     /.pickcmap_with_xlatmap cvx /configurationerror signalerror
  1141.   } if
  1142.   false
  1143.   .xlatmap_dict /TrueType get 
  1144.   dup length 2 sub 0 exch 2 exch {                       % bool [] i
  1145.     2 copy get                                           % bool [] i ()
  1146.     (.) search {                                         % bool [] i post match pre
  1147.       cvi exch pop exch cvi                              % bool [] i PlatID SpecID
  1148.     } {
  1149.       (gs/lib/xlatmap containg a record with an invalid (PlatformID.SpecificID)) =
  1150.       /.pickcmap_with_xlatmap cvx /configurationerror signalerror
  1151.     } ifelse
  1152.     TTFDEBUG {
  1153.       (Seeking a cmap for platform=) print 1 index =only ( encoding=) print dup =
  1154.     } if
  1155.     tabdict /cmap get                                    % bool [] i PlatID SpecID (cmap)
  1156.     dup /cmaptab exch def % temporary
  1157.     0 1 2 index 2 getu16a 1 sub {                        % bool [] i PlatID SpecID (cmap) j
  1158.       8 mul 4 add 1 index exch 8
  1159.       getinterval_from_stringarray                       % bool [] i PlatID SpecID (cmap) (cmapsub)
  1160.       TTFDEBUG {
  1161.         (cmap: platform ) print dup 0 getu16 =only
  1162.         ( encoding ) print dup 2 getu16 = flush
  1163.       } if
  1164.       dup 0 getu16 4 index eq {
  1165.         dup 2 getu16 3 index eq {                        % bool [] i PlatID SpecID (cmap) (cmapsub)
  1166.           TTFDEBUG {
  1167.             (Choosen a cmap for platform=) print 3 index =only
  1168.             ( encoding=) print 2 index =
  1169.           } if
  1170.           /cmapsub 1 index def
  1171.           dup 4 getu32                                   % bool [] i PlatID SpecID (cmap) (cmapsub) p
  1172.           cmaptab 1 index getu16a                        %     get cmap format
  1173.           8 lt {                                         %     length for traditional 16bit format 0, 2, 4, 6
  1174.             cmaptab 1 index 2 add getu16a
  1175.           } {                                            %     length for advanced 32bit format 8, 10, 12
  1176.             cmaptab 1 index 4 add getu32a
  1177.           } ifelse                                       % bool [] i PlatID SpecID (cmap) (cmapsub) p l
  1178.           cmaptab 3 1 roll getinterval_from_stringarray
  1179.           /cmaptab exch def                              % bool [] i PlatID SpecID (cmap) (cmapsub)
  1180.           5 index 5 index 1 add get                      % bool [] i PlatID SpecID (cmap) (cmapsub) /Decoding
  1181.           /Decoding exch def                             % bool [] i PlatID SpecID (cmap) (cmapsub)
  1182.           7 -1 roll pop true 7 1 roll                    % true [] i PlatID SpecID (cmap) (cmapsub)
  1183.         } if
  1184.       } if
  1185.       pop                                                % true [] i PlatID SpecID (cmap)
  1186.       5 index { exit } if
  1187.     } for                                                % bool [] i PlatID SpecID (cmap)
  1188.     pop pop pop pop                                      % bool []
  1189.     1 index { exit } if
  1190.   } for                                                  % bool []
  1191.   pop                                                    % bool
  1192.   not { 
  1193.     QUIET not { (True Type font doesn't contain a charset listed in gs/lib/xlatmap.) = } if
  1194.     /.pickcmap_with_xlatmap cvx /invalidfont signalerror
  1195.   } if                                                   %
  1196. } bind def
  1197.  
  1198. % - .pickcmap -
  1199. % Defines cmapsub, cmaptab
  1200. /.pickcmap {
  1201.   % Currently we use xlatmap only for emulation CIDFontType 2 with
  1202.   % a disk True Type font files, and use load_stripped
  1203.   % to check this regime. We would like to do so
  1204.   % while emulating a Type 42, but first the old code
  1205.   % about handling them to be changed 
  1206.   % with adding a handling of a Decoding.
  1207.   % fixme : A correct way to fix this is to implenent 
  1208.   % the Type 42 emulation with gs_fntem.ps .
  1209.   % Also note that PDF embedded fonts probably don't need a xlatmap -
  1210.   % see PDF spec, "Encodings for True Type fonts".
  1211.   load_stripped {
  1212.     //.pickcmap_with_xlatmap exec
  1213.   } {
  1214.     //.pickcmap_with_no_xlatmap exec
  1215.   } ifelse
  1216. } bind def
  1217.  
  1218. % <glyph> .nname <_name>
  1219. /.nname {
  1220.   =string cvs (_) exch concatstrings cvn
  1221. } bind def
  1222.  
  1223. % Provide alternative backward-compatible names for new TTF glyphs.
  1224. % This list was extracted from Adobe's Glyph List 2.0 and consists of
  1225. % glyph names that map to the same Unicode value.
  1226. % See: http://partners.adobe.com/asn/developer/typeforum/unicodegn.html
  1227. /postalias mark
  1228.   /pi1  /pi                                            /plusinus /plusminus
  1229.   /Acyrillic /afii10017                                /Becyrillic /afii10018                               
  1230.   /Cdot /Cdotaccent                                    /Checyrillic /afii10041                              
  1231.   /Dcroat /Dslash                                      /Decyrillic /afii10021                               
  1232.   /Delta /increment                                    /Djecyrillic /afii10051                              
  1233.   /Dzecyrillic /afii10054                              /Dzhecyrillic /afii10145                             
  1234.   /Ecyrillic /afii10053                                /Edot /Edotaccent                                    
  1235.   /Efcyrillic /afii10038                               /Elcyrillic /afii10029                               
  1236.   /Emcyrillic /afii10030                               /Encyrillic /afii10031                               
  1237.   /Ercyrillic /afii10034                               /Ereversedcyrillic /afii10047                        
  1238.   /Escyrillic /afii10035                               /Euro /euro                                          
  1239.   /Fitacyrillic /afii10147                             /Gcedilla /Gcommaaccent                              
  1240.   /Gdot /Gdotaccent                                    /Gecyrillic /afii10020                               
  1241.   /Gheupturncyrillic /afii10050                        /Gjecyrillic /afii10052                              
  1242.   /H18533 /blackcircle                                 /H18543 /blacksmallsquare                            
  1243.   /H18551 /whitesmallsquare                            /H22073 /whitesquare                                 
  1244.   /Hardsigncyrillic /afii10044                         /IAcyrillic /afii10049                               
  1245.   /IUcyrillic /afii10048                               /Icyrillic /afii10055                                
  1246.   /Idot /Idotaccent                                    /Iecyrillic /afii10022                               
  1247.   /Iicyrillic /afii10026                               /Iishortcyrillic /afii10027                          
  1248.   /Iocyrillic /afii10023                               /Izhitsacyrillic /afii10148                          
  1249.   /Jecyrillic /afii10057                               /Kacyrillic /afii10028                               
  1250.   /Kcedilla /Kcommaaccent                              /Khacyrillic /afii10039                              
  1251.   /Kjecyrillic /afii10061                              /Lcedilla /Lcommaaccent                              
  1252.   /Ldot /Ldotaccent                                    /Ljecyrillic /afii10058                              
  1253.   /Ncedilla /Ncommaaccent                              /Njecyrillic /afii10059                              
  1254.   /Ocyrillic /afii10032                                /Odblacute /Ohungarumlaut                            
  1255.   /Ohm /Omega                                          /Oslashacute /Ostrokeacute                           
  1256.   /Pecyrillic /afii10033                               /Rcedilla /Rcommaaccent                              
  1257.   /Shacyrillic /afii10042                              /Shchacyrillic /afii10043                            
  1258.   /Softsigncyrillic /afii10046                         /Tcedilla /Tcommaaccent                              
  1259.   /Tecyrillic /afii10036                               /Tsecyrillic /afii10040                              
  1260.   /Tshecyrillic /afii10060                             /Ucyrillic /afii10037                                
  1261.   /Udblacute /Uhungarumlaut                            /Upsilon1 /Upsilonhooksymbol                         
  1262.   /Ushortcyrillic /afii10062                           /Vecyrillic /afii10019                               
  1263.   /Yatcyrillic /afii10146                              /Yericyrillic /afii10045                             
  1264.   /Yicyrillic /afii10056                               /Zdot /Zdotaccent                                    
  1265.   /Zecyrillic /afii10025                               /Zhecyrillic /afii10024                              
  1266.   /acutecmb /acutecomb                                 /acyrillic /afii10065                                
  1267.   /afii00208 /horizontalbar                            /afii08941 /lira                                     
  1268.   /afii10066 /becyrillic                               /afii10067 /vecyrillic                               
  1269.   /afii10068 /gecyrillic                               /afii10069 /decyrillic                               
  1270.   /afii10070 /iecyrillic                               /afii10071 /iocyrillic                               
  1271.   /afii10072 /zhecyrillic                              /afii10073 /zecyrillic                               
  1272.   /afii10074 /iicyrillic                               /afii10075 /iishortcyrillic                          
  1273.   /afii10076 /kacyrillic                               /afii10077 /elcyrillic                               
  1274.   /afii10078 /emcyrillic                               /afii10079 /encyrillic                               
  1275.   /afii10080 /ocyrillic                                /afii10081 /pecyrillic                               
  1276.   /afii10082 /ercyrillic                               /afii10083 /escyrillic                               
  1277.   /afii10084 /tecyrillic                               /afii10085 /ucyrillic                                
  1278.   /afii10086 /efcyrillic                               /afii10087 /khacyrillic                              
  1279.   /afii10088 /tsecyrillic                              /afii10089 /checyrillic                              
  1280.   /afii10090 /shacyrillic                              /afii10091 /shchacyrillic                            
  1281.   /afii10092 /hardsigncyrillic                         /afii10093 /yericyrillic                             
  1282.   /afii10094 /softsigncyrillic                         /afii10095 /ereversedcyrillic                        
  1283.   /afii10096 /iucyrillic                               /afii10097 /iacyrillic                               
  1284.   /afii10098 /gheupturncyrillic                        /afii10099 /djecyrillic                              
  1285.   /afii10100 /gjecyrillic                              /afii10101 /ecyrillic                                
  1286.   /afii10102 /dzecyrillic                              /afii10103 /icyrillic                                
  1287.   /afii10104 /yicyrillic                               /afii10105 /jecyrillic                               
  1288.   /afii10106 /ljecyrillic                              /afii10107 /njecyrillic                              
  1289.   /afii10108 /tshecyrillic                             /afii10109 /kjecyrillic                              
  1290.   /afii10110 /ushortcyrillic                           /afii10193 /dzhecyrillic                             
  1291.   /afii10194 /yatcyrillic                              /afii10195 /fitacyrillic                             
  1292.   /afii10196 /izhitsacyrillic                          /afii10846 /schwacyrillic                            
  1293.   /afii57381 /percentarabic                            /afii57388 /commaarabic                              
  1294.   /afii57392 /zeroarabic                               /afii57393 /onearabic                                
  1295.   /afii57394 /twoarabic                                /afii57395 /threearabic                              
  1296.   /afii57396 /fourarabic                               /afii57397 /fivearabic                               
  1297.   /afii57398 /sixarabic                                /afii57399 /sevenarabic                              
  1298.   /afii57400 /eightarabic                              /afii57401 /ninearabic                               
  1299.   /afii57403 /semicolonarabic                          /afii57407 /questionarabic                           
  1300.   /afii57409 /hamzaarabic                              /afii57410 /alefmaddaabovearabic                     
  1301.   /afii57411 /alefhamzaabovearabic                     /afii57412 /wawhamzaabovearabic                      
  1302.   /afii57413 /alefhamzabelowarabic                     /afii57414 /yehhamzaabovearabic                      
  1303.   /afii57415 /alefarabic                               /afii57416 /beharabic                                
  1304.   /afii57417 /tehmarbutaarabic                         /afii57418 /teharabic                                
  1305.   /afii57419 /theharabic                               /afii57420 /jeemarabic                               
  1306.   /afii57421 /haharabic                                /afii57422 /khaharabic                               
  1307.   /afii57423 /dalarabic                                /afii57424 /thalarabic                               
  1308.   /afii57425 /reharabic                                /afii57426 /zainarabic                               
  1309.   /afii57427 /seenarabic                               /afii57428 /sheenarabic                              
  1310.   /afii57429 /sadarabic                                /afii57430 /dadarabic                                
  1311.   /afii57431 /taharabic                                /afii57432 /zaharabic                                
  1312.   /afii57433 /ainarabic                                /afii57434 /ghainarabic                              
  1313.   /afii57440 /tatweelarabic                            /afii57441 /feharabic                                
  1314.   /afii57442 /qafarabic                                /afii57443 /kafarabic                                
  1315.   /afii57444 /lamarabic                                /afii57445 /meemarabic                               
  1316.   /afii57446 /noonarabic                               /afii57448 /wawarabic                                
  1317.   /afii57449 /alefmaksuraarabic                        /afii57450 /yeharabic                                
  1318.   /afii57451 /fathatanarabic                           /afii57452 /dammatanarabic                           
  1319.   /afii57453 /kasratanarabic                           /afii57454 /fathaarabic                              
  1320.   /afii57455 /dammaarabic                              /afii57456 /kasraarabic                              
  1321.   /afii57457 /shaddaarabic                             /afii57458 /sukunarabic                              
  1322.   /afii57470 /heharabic                                /afii57505 /veharabic                                
  1323.   /afii57506 /peharabic                                /afii57507 /tcheharabic                              
  1324.   /afii57508 /jeharabic                                /afii57509 /gafarabic                                
  1325.   /afii57511 /tteharabic                               /afii57512 /ddalarabic                               
  1326.   /afii57513 /rreharabic                               /afii57514 /noonghunnaarabic                         
  1327.   /afii57519 /yehbarreearabic                          /afii57636 /newsheqelsign                            
  1328.   /afii57645 /maqafhebrew                              /afii57658 /sofpasuqhebrew                           
  1329.   /afii57664 /alef                                     /afii57665 /bet                                      
  1330.   /afii57666 /gimel                                    /afii57667 /dalet                                    
  1331.   /afii57668 /he                                       /afii57669 /vav                                      
  1332.   /afii57670 /zayin                                    /afii57671 /het                                      
  1333.   /afii57672 /tet                                      /afii57673 /yod                                      
  1334.   /afii57674 /finalkaf                                 /afii57675 /kaf                                      
  1335.   /afii57676 /lamed                                    /afii57677 /finalmem                                 
  1336.   /afii57678 /mem                                      /afii57679 /finalnun                                 
  1337.   /afii57680 /nun                                      /afii57681 /samekh                                   
  1338.   /afii57682 /ayin                                     /afii57683 /finalpe                                  
  1339.   /afii57684 /pe                                       /afii57685 /finaltsadi                               
  1340.   /afii57686 /tsadi                                    /afii57687 /qof                                      
  1341.   /afii57688 /resh                                     /afii57689 /shin                                     
  1342.   /afii57690 /tav                                      /afii57694 /shinshindot                              
  1343.   /afii57695 /shinsindot                               /afii57700 /vavholam                                 
  1344.   /afii57705 /doubleyodpatah                           /afii57716 /vavvavhebrew                             
  1345.   /afii57717 /vavyodhebrew                             /afii57718 /yodyodhebrew                             
  1346.   /afii57723 /vavdagesh                                /afii57793 /hiriq                                    
  1347.   /afii57794 /tsere                                    /afii57795 /segol                                    
  1348.   /afii57796 /qubuts                                   /afii57797 /qamats                                   
  1349.   /afii57798 /patah                                    /afii57799 /sheva                                    
  1350.   /afii57800 /hatafpatah                               /afii57801 /hatafsegol                               
  1351.   /afii57802 /hatafqamats                              /afii57803 /sindothebrew                             
  1352.   /afii57804 /shindothebrew                            /afii57806 /holam                                    
  1353.   /afii57807 /dagesh                                   /afii57839 /siluqhebrew                              
  1354.   /afii57841 /rafe                                     /afii57842 /paseqhebrew                              
  1355.   /afii57929 /apostrophemod                            /afii61248 /careof                                   
  1356.   /afii61289 /lsquare                                  /afii61352 /numero                                   
  1357.   /afii61664 /zerowidthnonjoiner                       /afii63167 /asteriskarabic                           
  1358.   /afii64937 /commareversedmod                         /alefmaksurainitialarabic /yehinitialarabic          
  1359.   /alefmaksuramedialarabic /yehmedialarabic            /approximatelyequal /congruent                       
  1360.   /arrowdblboth /dblarrowleft                          /arrowdblleft /arrowleftdbl                          
  1361.   /arrowdblright /dblarrowright                        /arrowupdnbse /arrowupdownbase                       
  1362.   /bar /verticalbar                                    /betdagesh /betdageshhebrew                          
  1363.   /blackdownpointingtriangle /triagdn                  /blackleftpointingpointer /triaglf                   
  1364.   /blackrectangle /filledrect                          /blackrightpointingpointer /triagrt                  
  1365.   /blacksmilingface /invsmileface                      /blacksquare /filledbox                              
  1366.   /blackuppointingtriangle /triagup                    /bulletinverse /invbullet                            
  1367.   /cdot /cdotaccent                                    /circle /whitecircle                                 
  1368.   /circlemultiply /timescircle                         /circleplus /pluscircle                              
  1369.   /club /clubsuitblack                                 /colonmonetary /colonsign                            
  1370.   /compass /sun                                        /daletdagesh /daletdageshhebrew                      
  1371.   /dargahebrew /dargalefthebrew                        /dbllowline /underscoredbl                           
  1372.   /dcroat /dmacron                                     /decimalseparatorarabic /decimalseparatorpersian     
  1373.   /dialytikatonos /dieresistonos                       /dkshade /shadedark                                  
  1374.   /dotbelowcmb /dotbelowcomb                           /edot /edotaccent                                    
  1375.   /eighthnotebeamed /musicalnotedbl                    /etnahtafoukhhebrew /etnahtahebrew                   
  1376.   /existential /thereexists                            /female /venus                                       
  1377.   /finalkafdagesh /finalkafdageshhebrew                /forall /universal                                   
  1378.   /gcedilla /gcommaaccent                              /gdot /gdotaccent                                    
  1379.   /gimeldagesh /gimeldageshhebrew                      /gradient /nabla                                     
  1380.   /gravecmb /gravecomb                                 /haaltonearabic /hehaltonearabic                     
  1381.   /heart /heartsuitblack                               /hedagesh /hedageshhebrew                            
  1382.   /hehfinalalttwoarabic /hehfinalarabic                /hookabovecomb /hookcmb                              
  1383.   /ilde /tilde                                         /integralbottom /integralbt                          
  1384.   /integraltop /integraltp                             /invcircle /whitecircleinverse                       
  1385.   /kafdagesh /kafdageshhebrew                          /kcedilla /kcommaaccent                              
  1386.   /lameddagesh /lameddageshhebrew                      /lcedilla /lcommaaccent                              
  1387.   /ldot /ldotaccent                                    /logicalnotreversed /revlogicalnot                   
  1388.   /longs /slong                                        /ltshade /shadelight                                 
  1389.   /macron /overscore                                   /mahapakhhebrew /mahapakhlefthebrew                  
  1390.   /male /mars                                          /memdagesh /memdageshhebrew                          
  1391.   /merkhahebrew /merkhalefthebrew                      /merkhakefulahebrew /merkhakefulalefthebrew          
  1392.   /middot /periodcentered                              /mu /mu1                                             
  1393.   /munahhebrew /munahlefthebrew                        /napostrophe /quoterightn                            
  1394.   /nbspace /nonbreakingspace                           /ncedilla /ncommaaccent                              
  1395.   /notelement /notelementof                            /nundagesh /nundageshhebrew                          
  1396.   /odblacute /ohungarumlaut                            /omega1 /pisymbolgreek                               
  1397.   /openbullet /whitebullet                             /orthogonal /rightangle                              
  1398.   /oslashacute /ostrokeacute                           /pedagesh /pedageshhebrew                            
  1399.   /phi1 /phisymbolgreek                                /propersubset /subset                                
  1400.   /propersuperset /superset                            /qofdagesh /qofdageshhebrew                          
  1401.   /quoteleftreversed /quotereversed                    /rcedilla /rcommaaccent                              
  1402.   /reflexsubset /subsetorequal                         /reflexsuperset /supersetorequal                     
  1403.   /reviahebrew /reviamugrashhebrew                     /samekhdagesh /samekhdageshhebrew                    
  1404.   /sfthyphen /softhyphen                               /shade /shademedium                                  
  1405.   /sheqel /sheqelhebrew                                /shindagesh /shindageshhebrew                        
  1406.   /shindageshshindot /shindageshshindothebrew          /shindageshsindot /shindageshsindothebrew            
  1407.   /sigma1 /sigmafinal                                  /similar /tildeoperator                              
  1408.   /smileface /whitesmilingface                         /space /spacehackarabic                              
  1409.   /spade /spadesuitblack                               /tavdages /tavdagesh                                 
  1410.   /tcedilla /tcommaaccent                              /tetdagesh /tetdageshhebrew                          
  1411.   /tevirhebrew /tevirlefthebrew                        /theta1 /thetasymbolgreek                            
  1412.   /thousandsseparatorarabic /thousandsseparatorpersian /tildecmb /tildecomb                                 
  1413.   /tipehahebrew /tipehalefthebrew                      /tsadidagesh /tsadidageshhebrew                      
  1414.   /twodotenleader /twodotleader                        /udblacute /uhungarumlaut                            
  1415.   /yerahbenyomohebrew /yerahbenyomolefthebrew          /yoddagesh /yoddageshhebrew                          
  1416.   /zayindagesh /zayindageshhebrew                      /zdot /zdotaccent                                    
  1417. .dicttomark readonly def
  1418.  
  1419. % - .charkeys /CharStrings <charstrings> /Encoding <encoding>
  1420. % Resets glyphencoding
  1421. /.charkeys {
  1422.   TTFDEBUG {
  1423.     (glyphencoding: length=) print glyphencoding dup length = === flush
  1424.   } if
  1425.         % Hack: if there is no usable post table but the cmap uses
  1426.         % the Microsoft Unicode encoding, use ISOLatin1Encoding.
  1427.      % if 'post' presents, .charkeys computes (with dropping minor details) :
  1428.      %     CharStrings = glyphencoding^-1
  1429.      %     Encoding = cmap*glyphencoding
  1430.      % because 'post' maps glyph indices to glyph names.
  1431.      % Otherwise .charkeys must compute (with dropping same details) :
  1432.      %     CharStrings = glyphencoding^-1 * cmap
  1433.      %     Encoding = glyphencoding
  1434.      % because glyphencoding is stubbed with an encoding, 
  1435.      % which maps char codes to glyph names.
  1436.   glyphencoding length 0 eq {
  1437.     /have_post false def
  1438.     cmapsub 0 4 getinterval <00030001> eq {
  1439.     PDFDEBUG { (No post but have cmap 3.1, so use ISOLatin1Encoding) = } if
  1440.       /glyphencoding ISOLatin1Encoding dup length array copy def
  1441.     } {
  1442.       PDFDEBUG { (No encoding info, use .GS_extended_SymbolEncoding) = } if
  1443.       /glyphencoding /.GS_extended_SymbolEncoding findencoding dup length array copy def
  1444.     } ifelse
  1445.   } {
  1446.     /have_post true def
  1447.   } ifelse
  1448.         % If necessary, fabricate additional glyphencoding entries
  1449.         % to cover all of loca
  1450.   glyphencoding length numloca lt {
  1451.     /glyphencoding numloca array
  1452.       glyphencoding length dup 1 sub 0 1 3 2 roll {
  1453.         dup glyphencoding exch get
  1454.         3 index 3 1 roll put
  1455.       } for
  1456.       % /glyphencoding <newarray> <glyphencoding length>
  1457.       1 numloca 1 sub {
  1458.         1 index exch dup .nname put
  1459.       } for
  1460.     def
  1461.   } if
  1462.   /cmapa cmaptab cmaparray def
  1463.         % Some badly designed Chinese fonts have a post table
  1464.         % in which all glyphs other than 0 are named .null.
  1465.         % Use CharStrings to keep track of the reverse map from
  1466.         % names to glyphs, and don't let any name be used for
  1467.         % more than one glyph.
  1468.   /CharStrings glyphencoding dup length 1 add dict    % +1 for .notdef
  1469.     0 1 3 index length 1 sub {
  1470.         % Stack: glyphencoding dict index
  1471.       2 index 1 index get 
  1472.       have_post not { 
  1473.         exch
  1474.         cmapa exch .knownget not {
  1475.           0   % a stub for a while. Must skip the entry.
  1476.         } if
  1477.         exch
  1478.       } if
  1479.       2 index 1 index known
  1480.       { % The same name maps to more than one glyph. Change the name.
  1481.         % No special treatment for /.notdef glyph. Bug 689408.
  1482.            pop dup .nname 3 index 2 index 2 index put
  1483.         2 index exch 3 -1 roll put
  1484.       } {
  1485.         2 index exch 3 -1 roll put    % unique name
  1486.       } ifelse
  1487.     } for exch pop
  1488.         % If there is no .notdef entry, map it to glyph 0.
  1489.   dup /.notdef known not { dup /.notdef 0 put } if
  1490.   TTFDEBUG { 
  1491.     (CharStrings:)= dup { exch =string cvs print ( ) print == } forall
  1492.   } if
  1493.   //postalias {
  1494.     % process pairs of names. If both names are known, do nothing. Otherwise
  1495.     % make the name that is not defined an alias for the one that does exist.
  1496.     % Stack: CharStrings(dict) /name1 /name2
  1497.     2 index 2 index known 3 index 2 index known 1 index xor not {
  1498.       pop pop pop    % both names known or neither known
  1499.     } {
  1500.       % Stack: CharStrings(dict) /name1 /name2 name1_known(bool)
  1501.       { exch } if        % /name1 known -- we need it on top 
  1502.       % Stack: CharStrings(dict) /alias_name /known_name
  1503.       TTFDEBUG { (setting alias: ) print 1 index ==only ( to be the same as glyph: ) print dup == } if
  1504.       2 index exch get 2 index 3 1 roll put
  1505.     } ifelse  
  1506.   } forall
  1507.   readonly
  1508.   /Encoding [
  1509.       have_post {
  1510.         0 1 255 {
  1511.           cmapa exch .knownget not { 0 } if
  1512.           glyphencoding dup length
  1513.           2 index le {
  1514.             pop pop /.notdef
  1515.           } {
  1516.             exch get
  1517.           } ifelse
  1518.         } for
  1519.       } {
  1520.         glyphencoding  dup length 256 gt { 0 256 getinterval } if
  1521.         aload pop
  1522.         counttomark 256 exch sub { /.notdef } repeat
  1523.       } ifelse
  1524.     ]
  1525.   TTFDEBUG { (Encoding: ) print dup === flush } if
  1526. } bind def
  1527.  
  1528. currentdict /postalias undef
  1529.  
  1530. % <file> .loadttfont <type42font>
  1531. /.loadttfont {
  1532.   TTFDEBUG { (.loadttfont) = } if
  1533.   //false 0 .loadttfonttables
  1534.   .makesfnts
  1535.   .getpost
  1536.   .pickcmap
  1537.   mark
  1538.   .charkeys
  1539.   .ttkeys
  1540.   /FontType 42
  1541.   /PaintType 0
  1542.   TTFDEBUG {
  1543.     (numloca=) print numloca =
  1544.   } if
  1545.   .dicttomark
  1546.   end end dup /FontName get exch definefont
  1547. } bind def
  1548.  
  1549. % ---------------- CIDFontType 2 font loading ---------------- %
  1550.  
  1551. % Fill a string with sequential CIDs starting from the initial value.
  1552. % <string> <value> .fill_identity_cmap <string>
  1553. /.fill_identity_cmap {             % () v
  1554.   1 index length 2 sub          % () v n-2
  1555.   0 2 3 2 roll {                % () v 0 2 n-1
  1556.       3 copy exch               % () v i () i v 
  1557.       -8 bitshift               % () v i () i v>>8
  1558.       put                       % () v i
  1559.       3 copy 1 add              % () v i () v i+1
  1560.       exch 255 and              % () v i () i+1 v&255
  1561.       put                       % () v i 
  1562.       pop 1 add                 % () v+1
  1563.   } for
  1564.   pop
  1565. } bind def
  1566.  
  1567. % -mark- <key> <value> ... .definettcidfont <font>
  1568. /.definettcidfont {
  1569.   /CIDFontName fontname
  1570.   /CIDFontType 2
  1571.   /CIDSystemInfo mark
  1572.     /Registry (Adobe)
  1573.     /Ordering (Japan1)        % adhoc
  1574.     /Supplement 0
  1575.   .dicttomark
  1576.   /CharStrings mark /.notdef 0 .dicttomark
  1577.         % The cmap isn't of any use even if it is present.
  1578.         % Just construct an identity CIDMap covering all the glyphs.
  1579.  
  1580.   /CIDCount numloca % Wrong if a CIDFontType2 embedded into PDF with a non-Identity CIDToGIDMap.
  1581.                     % processCIDToGIDMap may replace.
  1582.   /CIDMap numloca maxstring le {
  1583.                 % Use a single string.
  1584.       numloca 2 mul string 0 .fill_identity_cmap
  1585.   } {
  1586.                 % We must use 2 strings.
  1587.       maxstring 2 mul string 0 .fill_identity_cmap
  1588.       numloca maxstring sub 2 mul string maxstring .fill_identity_cmap
  1589.       2 array astore
  1590.   } ifelse
  1591.  
  1592.   /GDBytes 2
  1593.   .dicttomark
  1594.   end end dup /CIDFontName get exch /CIDFont defineresource
  1595. } bind def
  1596.  
  1597. % <file> .loadttcidfont <cidtype2font>
  1598. /.loadttcidfont {
  1599.   //false 0 .loadttfonttables
  1600.   .makesfnts
  1601.     % CIDFontType2 fonts don't have a cmap: they are indexed by CID.
  1602.   mark
  1603.   .ttkeys
  1604.   .definettcidfont
  1605. } bind def
  1606.  
  1607. % <file> <SubfontID> .load_tt_font_stripped <font_data>
  1608. % The font_data includes sfnts, NumGlyphs, TT_cmap, file_table_pos, Decoding.
  1609. % CIDMap to be created later from TT_cmap.
  1610. /.load_tt_font_stripped {
  1611.   //true exch .loadttfonttables
  1612.   .makesfnts
  1613.   .pickcmap
  1614.   mark
  1615.   .ttkeys
  1616.   /NumGlyphs numloca
  1617.   /TT_cmap cmaptab cmaparray
  1618.   /file_table_pos file_table_pos
  1619.   /Decoding Decoding
  1620.   .dicttomark
  1621.   end end 
  1622. } bind def
  1623.  
  1624. % ---------------- PDF TrueType font loading ---------------- %
  1625.  
  1626. % Strictly speaking, this code should be loaded only if we have a PDF
  1627. % interpreter, but it's so closely tied to the rest of the code in this
  1628. % file that we always include it.
  1629.  
  1630. % <plat+enc> .findcmap <subtable> true
  1631. % <plat+enc> .findcmap false
  1632. /.findcmap {
  1633.   false exch tabdict /cmap get
  1634.         % Some fonts have multiple cmaps with the same platform and
  1635.         % encoding.  Use the first one we find.
  1636.   0 1 2 index 2 getu16a 1 sub {
  1637.         % Stack: false plat+enc cmap index
  1638.     8 mul 4 add 1 index exch 8 getinterval_from_stringarray
  1639.     dup 0 4 getinterval 3 index eq {
  1640.       4 getu32 1 index exch 1 index string_array_size 1 index sub getinterval_from_stringarray
  1641.       4 -1 roll not 4 2 roll exit
  1642.     } if pop
  1643.   } for
  1644.         % Stack: false plat+enc cmap || subtable true plat+enc cmap
  1645.   pop pop
  1646. } bind def
  1647.  
  1648. % Build .symbol_list for .pdfcharkeys .
  1649. % It is a dictionary containing all SymbolEncoding glyph names
  1650. % and random names for filling gaps in the character code range.
  1651. /.symbol_list 256 dict def
  1652. {
  1653.   =string 0 (x) 0 get put
  1654.   /SymbolEncoding .findencoding
  1655.   0 1 255 {
  1656.     dup 2 index exch get
  1657.     dup /.notdef eq {
  1658.       pop dup
  1659.       =string 1 3 getinterval cvs length 1 add
  1660.       =string exch 0 exch getinterval cvn
  1661.     } if
  1662.     exch //.symbol_list 3 1 roll put
  1663.   } for
  1664.   pop
  1665. } bind exec
  1666.  
  1667. % Create .GS_extended_SymbolEncoding as inverse of .symbol_list .
  1668. {
  1669.   /.GS_extended_SymbolEncoding 256 array
  1670.   //.symbol_list {
  1671.     exch 2 index 3 1 roll put  
  1672.   } forall
  1673.   .defineencoding
  1674. } bind exec
  1675.  
  1676. /.hexdigits (0123456789ABCDEF) def
  1677.  
  1678. /.is_hex_digit { %   <int> .is_hex_digit <bool>
  1679.   dup 48 ge exch
  1680.   dup 57 le exch
  1681.   dup 65 ge exch
  1682.   70 le and 
  1683.   3 1 roll
  1684.   and or
  1685. } bind def
  1686.  
  1687. /.popfex { pop //false exit } bind def
  1688. /.pop3ex { pop pop pop exit } bind def
  1689.  
  1690. /.addglyph {  % <dict> <name> <glyph#> .addglyph -
  1691.   1 index .namestring     % d n g s
  1692.   dup length 7 eq { 
  1693.     % Bug688467.ps doesn't work if the uniXXXX mapping is allowed with any cmap.
  1694.     % Allow it with cmap 3.1 only.
  1695.     currentdict /.allow_uniXXXX_glyph_names .knownget not { //false } if 
  1696.     } { //false 
  1697.     } ifelse              % d n g s b
  1698.   {
  1699.     % An undocumented Adobe feature (not sure) :
  1700.     % if the name is uniXXXX, obtain Unicode code from it.
  1701.     % See bug 688946.
  1702.     TTFDEBUG { (Try uniXXXX:) print dup print } if
  1703.     { dup 0 get 117 ne //.popfex if % u
  1704.       dup 1 get 110 ne //.popfex if % n
  1705.       dup 2 get 105 ne //.popfex if % i
  1706.       dup 3 get //.is_hex_digit exec not //.popfex if
  1707.       dup 4 get //.is_hex_digit exec not //.popfex if
  1708.       dup 5 get //.is_hex_digit exec not //.popfex if
  1709.       dup 6 get //.is_hex_digit exec not //.popfex if
  1710.       dup 3 1 getinterval .hexdigits exch search pop length exch pop exch pop 12 bitshift exch
  1711.       dup 4 1 getinterval .hexdigits exch search pop length exch pop exch pop  8 bitshift exch
  1712.       dup 5 1 getinterval .hexdigits exch search pop length exch pop exch pop  4 bitshift exch
  1713.       dup 6 1 getinterval .hexdigits exch search pop length exch pop exch pop exch pop
  1714.       add add add 
  1715.  
  1716.       cmapencoding exch .knownget not { 0 } if
  1717.       dup 0 eq //.popfex if
  1718.  
  1719.       TTFDEBUG { ( index=) print dup =string cvs print } if
  1720.       exch pop
  1721.       put //true exit
  1722.     } loop
  1723.     TTFDEBUG { ()= } if
  1724.   } {
  1725.     pop //false
  1726.   } ifelse
  1727.   not {                   % d n g
  1728.     {
  1729.       cmapencoding exch .knownget not { 0 } if
  1730.       dup 0 eq //.pop3ex if
  1731.       3 copy pop known //.pop3ex if
  1732.       put exit
  1733.     } loop
  1734.   } if
  1735. } bind def
  1736.  
  1737. % <subcmap> <chartoglyphmap> .pdfmapchars /CharStrings <charstrings>
  1738. /.pdfmapchars {
  1739.   exch cmaparray /cmapencoding exch def     % c2g
  1740.   /CharStrings 0 dict                       % c2g /CS <<>>
  1741.  
  1742.   % Add glyphs of <chartoglyphmap>*<subcmap> :
  1743.   3 2 roll {                               % /CS <<>> v
  1744.     dup type /arraytype eq {               % /CS <<>> /name []
  1745.       { 3 copy //.addglyph exec
  1746.         pop
  1747.       } forall
  1748.     } {
  1749.       3 copy //.addglyph exec pop
  1750.     } ifelse
  1751.     pop
  1752.   } forall
  1753.  
  1754.   % Add glyphs of 'post' with lower priority :
  1755.   0 1 glyphencoding length 1 sub {
  1756.     dup glyphencoding exch get exch
  1757.     dup 0 ne {
  1758.       3 copy pop known not {
  1759.         3 copy put
  1760.       } if
  1761.     } if
  1762.     pop pop
  1763.   } for
  1764.  
  1765.   dup /.notdef 0 put
  1766.  
  1767. } bind def
  1768.  
  1769. % - .pdfcharkeys /CharStrings <charstrings> /Encoding <encoding>
  1770. /.pdfcharkeys {
  1771.     % The following algorithms are per the PDF Reference, Second Edition
  1772.     % (PDF 1.3 reference manual).
  1773.   TTFDEBUG { (.pdfcharkeys beg) = } if
  1774.   is_symbolic {
  1775.     <00030001> .findcmap {
  1776.       %
  1777.       % Adobe PDF spec says that symbolic fonts should contain exactly one 
  1778.       % cmap subtable for Platform=1, Encoding=0.
  1779.       % Perhaps "Adobe Acrobat PDFWriter 4.0 for Windows" sometimes embeds
  1780.       % fonts with both subtables 3.1 and 1.0 (see comparefiles/159.pdf,
  1781.       % the font "Arial,Bold" with the character "registered"),
  1782.       % and both Acrobat Reader 4.0 and 5.0 choose 3.1.
  1783.       % Therefore we try 3.1 first.
  1784.       %
  1785.       (   **** Warning: Embedded symbolic TT fonts should not contain a cmap for Platform=3 Encoding=1.\n)
  1786.         pdfformaterror
  1787.       prebuilt_encoding null ne {
  1788.         % Bug 689083.
  1789.         TTFDEBUG { (Using cmap 3.0 with prebuilt_encoding.) = } if
  1790.         prebuilt_encoding .invert_encoding .pdfmapchars
  1791.         /Encoding prebuilt_encoding
  1792.       } {
  1793.         TTFDEBUG { (Using cmap 3.1 with WinAnsiEncoding) = } if
  1794.         AdobeGlyphList .pdfmapchars 
  1795.         /Encoding /WinAnsiEncoding .findencoding
  1796.       } ifelse
  1797.     } {
  1798.       %
  1799.       % Adobe PDF spec says that in this case PDF interpreter should
  1800.       % map character codes directly to glyphs using
  1801.       % the cmap <00010000>. But we use PS interpreter to emulate
  1802.       % a PDF interpreter. Therefore we need to construct
  1803.       % a type 42 font, which requires an Encoding and a Charstrings.
  1804.       % We construct them with symbol_list, which
  1805.       % includes all glyphs from SymbolEncoding and additional
  1806.       % random names for 1-to-1 mapping.
  1807.       %
  1808.       % A real TT font may use a different characters than
  1809.       % the Symbol charaster set. Perhaps our code
  1810.       % will give a correct printing, because glyph names are not
  1811.       % important for symbolic fonts in PDF.
  1812.       %
  1813.       <00010000> .findcmap {
  1814.         prebuilt_encoding null ne {
  1815.           TTFDEBUG { (Using cmap 1.0 with prebuilt_encoding.) = } if
  1816.           prebuilt_encoding .invert_encoding .pdfmapchars
  1817.           /Encoding prebuilt_encoding
  1818.         } {
  1819.           % This is a case, in which an obsolete software could stupidly specify Macintosh Roman
  1820.           % for a random encoding. Particulatrly GPL Ghostscript 7.06 does so.
  1821.           % Trying to recover with 'post'.
  1822.           pop  % The table itself doesn't contain useful data.
  1823.           TTFDEBUG { (Using cmap 1.0 with post or .GS_extended_SymbolEncoding) = } if
  1824.           .charkeys
  1825.         } ifelse
  1826.       } {
  1827.         % This is illegal with PDF spec.
  1828.         (   **** Warning: Embedded symbolic TT fonts must contain a cmap for Platform=1 Encoding=0.\n)
  1829.         pdfformaterror
  1830.         % Apply the default algorithm. Hopely it has 'post'.
  1831.         .charkeys
  1832.         % check if the CharStrings dict contains glyphs needed by the
  1833.         % prebuilt_encoding otherwise try the 3,0 cmap.
  1834.     prebuilt_encoding null ne {
  1835.       false prebuilt_encoding {    % false means no missing glyphs
  1836.         4 index exch known not { pop true exit } if
  1837.           } forall
  1838.           {
  1839.         (   **** Warning: Encoding derived from 'post' is incomplete.\n)
  1840.         pdfformaterror
  1841.         % Try another cmap format 3,0 -- Adobe doesn't mention it, but does
  1842.         % use it apparently (empirically determined).
  1843.         <00030000> .findcmap {
  1844.           TTFDEBUG { (Adding cmap 3.0) = } if
  1845.              5 1 roll pop pop pop pop             
  1846.           prebuilt_encoding null ne {
  1847.           prebuilt_encoding .invert_encoding .pdfmapchars
  1848.           /Encoding prebuilt_encoding
  1849.         } {
  1850.           AdobeGlyphList .pdfmapchars
  1851.           /Encoding /SymbolEncoding .findencoding
  1852.           } ifelse
  1853.         } if
  1854.           } if
  1855.         } if
  1856.       } ifelse
  1857.     } ifelse
  1858.   } {
  1859.     <00030001> .findcmap {
  1860.       prebuilt_encoding null ne {
  1861.         TTFDEBUG { (Using cmap 3.1 with prebuilt_encoding for non-symbolic.) = } if
  1862.  
  1863.         % The character code in /prebuilt_encoding[] is not guaranteed to be
  1864.         % compatible with the Microsoft UCS2 TrueType cmap subtable.
  1865.         % If the glyphname is known by AdobeGlyphList, the charcode for the glyph
  1866.         % is replaced by UCS2 charcode from AdobeGlyphList. Otherwise it is left
  1867.         % as in /prebuilt_encoding[]. /.pdfmapchars should dredge them.
  1868.  
  1869.       /.allow_uniXXXX_glyph_names //true def
  1870.         AdobeGlyphList prebuilt_encoding .invert_encoding dup {    % <<AGL>> <<pbe>> <glyphname> <pbecode>
  1871.           pop                                                      % <<AGL>> <<pbe>> <glyphname>
  1872.           TTFDEBUG { (check glypname /) print dup =only flush } if
  1873.           2 index 1 index .knownget {                              % <<AGL>> <<pbe>> <glyphname> <AGLcode>
  1874.             2 index 3 1 roll                                       % <<AGL>> <<pbe>> <<pbe>> <glyphname> <AGLcode>
  1875.             TTFDEBUG { ( redefine codepoint by AdobeGlyphList, ) print dup == flush } if
  1876.             put                                                    % <<AGL>> <<pbe>>
  1877.           } {                                                      % <<AGL>> <<pbe>> <glyphname>
  1878.             TTFDEBUG { ( unknown glyphname, leave as it is ) print flush } if
  1879.             pop                                                    % <<AGL>> <<pbe>>
  1880.           } ifelse
  1881.         } forall
  1882.         exch pop                                                   % <<pbe>>
  1883.         TTFDEBUG { dup (<<\n) print { exch (    ) print =only (\t) print == } forall (>>\n) print flush } if
  1884.         .pdfmapchars
  1885.         /Encoding prebuilt_encoding
  1886.       } {
  1887.         % Likely this branch is now obsolete.
  1888.         TTFDEBUG { (Using cmap 3.1 for non-symbolic.) = } if
  1889.         AdobeGlyphList .pdfmapchars 
  1890.         /Encoding /WinAnsiEncoding .findencoding
  1891.           % WinAnsiEncoding is just a stub here. 
  1892.           % It will be replaced with one from font resource,
  1893.           % because PDF spec requires it.
  1894.       } ifelse
  1895.     } {
  1896.       <00010000> .findcmap {
  1897.         TTFDEBUG { (Using cmap 1.0 for non-symbolic.) = } if
  1898.     .romanmacdict .pdfmapchars 
  1899.         /Encoding
  1900.         prebuilt_encoding null ne {
  1901.           prebuilt_encoding
  1902.         } {
  1903.           /MacRomanEncodingForTrueType .findencoding
  1904.         } ifelse
  1905.       } {
  1906.         % Apply the default algorithm for using the 'post'.
  1907.     .charkeys
  1908.       } ifelse
  1909.     } ifelse
  1910.   } ifelse
  1911.   TTFDEBUG { (.pdfcharkeys end) = } if
  1912. } bind def
  1913.  
  1914. % <file> <is_symbolic> <Encoding|null> .loadpdfttfont <type42font>
  1915. /.loadpdfttfont {
  1916.   TTFDEBUG { (.loadpdfttfont Encoding=) print dup == } if
  1917.   /prebuilt_encoding gput     % for .pdfcharkeys
  1918.   /is_symbolic gput
  1919.   //false 0 .loadttfonttables
  1920.   .makesfnts
  1921.   tabdict /cmap known not {
  1922.     (   **** Warning: Embedded TT font lacks required cmap table. Using identity cmap.\n)
  1923.         pdfformaterror
  1924.     % Unknown (i.e. not 0 ) language ID brings in post table.
  1925.     % Fields: cmap_version, number_of_subtables,
  1926.     %  plarform_id, encoding_id, offset,
  1927.     %  format, subtable_length, language,
  1928.     %  256 bytes of identity mapping.
  1929.     tabdict /cmap
  1930.     < 0000 0001
  1931.       0001 D00D 0000000c
  1932.       0000 0106 0000
  1933.       00 01 02 03 04 05 06 07 08 09 0a 0d 0c 0d 0e 0f
  1934.       10 11 12 13 14 15 16 17 18 19 1a 1d 1c 1d 1e 1f
  1935.       20 21 22 23 24 25 26 27 28 29 2a 2d 2c 2d 2e 2f
  1936.       30 31 32 33 34 35 36 37 38 39 3a 3d 3c 3d 3e 3f
  1937.       40 41 42 43 44 45 46 47 48 49 4a 4d 4c 4d 4e 4f
  1938.       50 51 52 53 54 55 56 57 58 59 5a 5d 5c 5d 5e 5f
  1939.       60 61 62 63 64 65 66 67 68 69 6a 6d 6c 6d 6e 6f
  1940.       70 71 72 73 74 75 76 77 78 79 7a 7d 7c 7d 7e 7f
  1941.       80 81 82 83 84 85 86 87 88 89 8a 8d 8c 8d 8e 8f
  1942.       90 91 92 93 94 95 96 97 98 99 9a 9d 9c 9d 9e 9f
  1943.       a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 aa ad ac ad ae af
  1944.       b0 b1 b2 b3 b4 b5 b6 b7 b8 b9 ba bd bc bd be bf
  1945.       c0 c1 c2 c3 c4 c5 c6 c7 c8 c9 ca cd cc cd ce cf
  1946.       d0 d1 d2 d3 d4 d5 d6 d7 d8 d9 da dd dc dd de df
  1947.       e0 e1 e2 e3 e4 e5 e6 e7 e8 e9 ea ed ec ed ee ef
  1948.       f0 f1 f2 f3 f4 f5 f6 f7 f8 f9 fa fd fc fd fe ff
  1949.     > readonly put
  1950.   } if
  1951.   .getpost
  1952.   .pickcmap
  1953.   mark
  1954.   .pdfcharkeys
  1955.   .ttkeys
  1956.   /FontType 42
  1957.   /PaintType 0
  1958.   TTFDEBUG {
  1959.     (numloca=) print numloca =
  1960.   } if
  1961.   .dicttomark
  1962.   end end
  1963.   .completefont
  1964. } bind def
  1965.